using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.Win32;
using System.Data.SqlClient;
using System.Diagnostics;

namespace MC.EventHandler.Install
{
    internal delegate void NotificationHandler(object sender, string message);

    internal class InstallExecutor
    {
        private readonly InstallationConfiguration _config;

        public InstallExecutor(InstallationConfiguration config)
        {
            _config = config;
        }
        public event NotificationHandler Notification;

        public void Install()
        {
            try
            {
                CheckPrerequisites();
                RunDBScripts();
                ConfigureIIS();
                DeployWebApplication();
                if (Notification != null)
                {
                    Notification(this, "The installation of Event Handler was successful.  Congratulations!");
                }
            }
            catch (Exception ex)
            {
                if (Notification != null)
                {
                    Notification(this, ex.Message);
                }
            }
        }

        private static void DeployWebApplication()
        {
            //TODO: Deploy Web Application
        }

        private static void ConfigureIIS()
        {
            //TODO: Configure IIS
        }

        private void RunDBScripts()
        {
            string exec = String.Format(@"SQL\InstallDB.bat");
            string args  = String.Format("{0} {1} {2}", _config.AdminDbUsername, _config.AdminDbPassword, _config.SQLServer);
            Process.Start(exec, args );
        }

        private void CheckPrerequisites()
        {
            CheckForIIS();
            CheckForASPdotNetMVC();
            CheckForDotNet3dot5();
            CheckForSQLServer2008();
        }

        private void CheckForIIS()
        {
            const string regKey = @"SOFTWARE\Microsoft\InetStp";
            using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(regKey))
            {
                if (rk == null)
                {
                    throw new Exception("The system does not have IIS Installed");
                }
            }
        }

        private void CheckForSQLServer2008()
        {
            //Try to connect to SQL Server
            using (IDbConnection cn = new SqlConnection(String.Format(@"Data Source={0};Initial Catalog=master;UID={1};PWD={2}", _config.SQLServer, _config.AdminDbUsername, _config.AdminDbPassword)))
            {
                try
                {
                    cn.Open();
                }
                catch (Exception)
                {
                    throw new Exception(String.Format("Unable to connect to SQLServer:{0} DBName:{1} UID:{2}", _config.SQLServer, _config.DBName, _config.AdminDbUsername));
                }
                try
                {
                    var cmd = cn.CreateCommand();
                    cmd.CommandText = "SELECT SERVERPROPERTY('ProductVersion')";
                    cmd.CommandType = CommandType.Text;
                    var version = cmd.ExecuteScalar() as string;
                    if (version != null)
                    {
                        if (int.Parse(version.Split('.')[0]) < 10)
                        {
                            throw new Exception("This application requires SQL Server 2008");
                        }
                    }
                }
                catch (Exception)
                {
                    throw new Exception("Unable to determine version of SQL Server");
                }
            }

        }

        private static void CheckForASPdotNetMVC()
        {
            const string regKey = @"SOFTWARE\Classes\Installer\Assemblies\Global";
            using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(regKey))
            {
                if (rk != null)
                {
                    List<string> SubKeyNames = new List<string>(rk.GetValueNames());
                    if (!SubKeyNames.Contains("System.Web.Mvc,version=\"1.0.0.0\",culture=\"neutral\",publicKeyToken=\"31BF3856AD364E35\",processorArchitecture=\"MSIL\""))
                    {
                        throw new Exception("The system does not have the Microsoft.Net Framework 3.5 SP1");
                    }
                }
                else
                {
                    throw new Exception("The system does not have the Microsoft.Net Framework 3.5 SP1");
                }
            }
        }

        private static void CheckForDotNet3dot5()
        {
            const string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
            using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(uninstallKey))
            {
                if (rk != null)
                {
                    List<string> SubKeyNames = new List<string>(rk.GetSubKeyNames());
                    if (!SubKeyNames.Contains("Microsoft .NET Framework 3.5 SP1"))
                    {
                        throw new Exception("The system does not have the Microsoft.Net Framework 3.5 SP1");
                    }
                }
                else
                {
                    throw new Exception("The system does not have the Microsoft.Net Framework 3.5 SP1");
                }
            }
        }
    }

}